﻿
namespace HSS.Xaml.UI.Media
{
	#region Using Directives
	using System;
	using System.ComponentModel;
	using System.Globalization;
	using System.Windows.Media;

	#endregion

	#region ColorConverter
	/// <summary>
	/// 
	/// </summary>
	public class ColorConverter : TypeConverter
	{
		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		/// <param name="sourceType"></param>
		/// <returns></returns>
		public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
		{
			return (sourceType == typeof(string)) || base.CanConvertFrom(context, sourceType);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		/// <param name="destinationType"></param>
		/// <returns></returns>
		public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
		{
			return ((destinationType == typeof(Color) ||
						destinationType == typeof(Int64) ||
						destinationType == typeof(KnownColor))
						|| base.CanConvertTo(context, destinationType));
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		/// <param name="culture"></param>
		/// <param name="value"></param>
		/// <returns></returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
		public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
		{
			if (value == null)
				throw this.GetConvertFromException(value);

			if (!(value is string))
				throw new ArgumentException("Can only convert from a String");

			return ParseColor(value as string);

		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="context"></param>
		/// <param name="culture"></param>
		/// <param name="value"></param>
		/// <param name="destinationType"></param>
		/// <returns></returns>
		public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
		{
			if ((destinationType != null) && (value is Color))
			{
				if (destinationType == typeof(Color))
				{
					var color2 = (Color)value;
					return Color.FromArgb(color2.A, color2.R, color2.G, color2.B);
				}

				if (destinationType == typeof(KnownColor))
					return KnownColors.KnownColorFromColor((Color)value);

				if (destinationType == typeof(string))
				{
					var knowncolor = KnownColors.KnownColorFromColor((Color)value);
					string colorName = knowncolor.ToString();
					if (colorName == "UnknownColor")
						return ((Color)value).ToString();
					else
						return colorName;
				}
			}
			return base.ConvertTo(context, culture, value, destinationType);
		}

		#region Helpers

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "IllegalToken")]
		internal static Color ParseColor(string color)
		{
			bool isNumericColor;
			bool isKnownColor;
			string trimmedColor = KnownColors.MatchColor(color, out isKnownColor, out isNumericColor);

			if (!isKnownColor && !isNumericColor)
				throw new FormatException("IllegalToken");

			if (isNumericColor)
				return ParseHexColor(trimmedColor);

			KnownColor colorName = KnownColors.ColorStringToKnownColor(trimmedColor);
			if (colorName == KnownColor.UnknownColor)
				throw new FormatException("IllegalToken");

			return colorName;
		}
		private static Color ParseHexColor(string trimmedColor)
		{
			int blue;
			int green;
			int red;
			int alpha = 0xff;
			if (trimmedColor.Length > 7)
			{
				alpha = (ParseHexChar(trimmedColor[1]) * 0x10) + ParseHexChar(trimmedColor[2]);
				red = (ParseHexChar(trimmedColor[3]) * 0x10) + ParseHexChar(trimmedColor[4]);
				green = (ParseHexChar(trimmedColor[5]) * 0x10) + ParseHexChar(trimmedColor[6]);
				blue = (ParseHexChar(trimmedColor[7]) * 0x10) + ParseHexChar(trimmedColor[8]);
			}
			else if (trimmedColor.Length > 5)
			{
				red = (ParseHexChar(trimmedColor[1]) * 0x10) + ParseHexChar(trimmedColor[2]);
				green = (ParseHexChar(trimmedColor[3]) * 0x10) + ParseHexChar(trimmedColor[4]);
				blue = (ParseHexChar(trimmedColor[5]) * 0x10) + ParseHexChar(trimmedColor[6]);
			}
			else if (trimmedColor.Length > 4)
			{
				alpha = ParseHexChar(trimmedColor[1]);
				alpha += alpha * 0x10;
				red = ParseHexChar(trimmedColor[2]);
				red += red * 0x10;
				green = ParseHexChar(trimmedColor[3]);
				green += green * 0x10;
				blue = ParseHexChar(trimmedColor[4]);
				blue += blue * 0x10;
			}
			else
			{
				red = ParseHexChar(trimmedColor[1]);
				red += red * 0x10;
				green = ParseHexChar(trimmedColor[2]);
				green += green * 0x10;
				blue = ParseHexChar(trimmedColor[3]);
				blue += blue * 0x10;
			}
			return Color.FromArgb((byte)alpha, (byte)red, (byte)green, (byte)blue);
		}
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "IllegalToken")]
		private static int ParseHexChar(char c)
		{
			int num = c;
			if ((num >= 0x30) && (num <= 0x39))
			{
				return (num - 0x30);
			}
			if ((num >= 0x61) && (num <= 0x66))
			{
				return ((num - 0x61) + 10);
			}
			if ((num < 0x41) || (num > 70))
			{
				throw new FormatException("IllegalToken");
			}
			return ((num - 0x41) + 10);
		}
		/// <summary>
		/// Not supported.
		/// </summary>
		/// <param name="value"></param>
		/// <returns>NotSupportedException</returns>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "ToStringNull"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", MessageId = "ConvertFromException")]
		protected Exception GetConvertFromException(object value)
		{
			string fullName;
			if (value == null)
				fullName = "ToStringNull";
			else
				fullName = value.GetType().FullName;

			throw new NotSupportedException("ConvertFromException for Converter: " + base.GetType().Name + " attempting to convert [ " + fullName + " ]");
		}

		#endregion
	}
	#endregion
}